package java_liaoxuefeng.annotationtest;

import android_design_mode.chapter21_decorator.cloth.Person;
import jdk.internal.org.objectweb.asm.tree.analysis.Value;

import javax.xml.ws.BindingType;
import java.lang.annotation.*;

/**
 * 所有基本类型；
 * String；
 * 枚举类型；
 * <p>
 * 基本类型、String、Class以及枚举的数组。
 * <p>
 * 元注解（meta annotation）：
 *
 * @Target ElementType ( ElementType[] value();)
 * 类或接口：ElementType.TYPE；
 * 字段：ElementType.FIELD；
 * 方法：ElementType.METHOD；
 * 构造方法：ElementType.CONSTRUCTOR；
 * 方法参数：ElementType.PARAMETER。
 * <p>
 * @Retention (默认为CLASS)
 * 仅编译期：RetentionPolicy.SOURCE；
 * 仅class文件：RetentionPolicy.CLASS；
 * 运行期：RetentionPolicy.RUNTIME。
 * <p>
 * @Repeatable <p>
 * @Inherited 使用@Inherited定义子类是否可继承父类定义的Annotation。
 * "@Inherited" 仅针对@Target(ElementType.TYPE)类型的annotation有效，
 * 并且仅针对class的继承，对interface的继承无效：
 * <p>
 * <p>
 * 使用反射API读取Annotation：
 * <p>
 * <p>
 * Class.getAnnotation(Class)
 * Field.getAnnotation(Class)
 * Method.getAnnotation(Class)
 * Constructor.getAnnotation(Class)
 */
public class Annotation001 {

    /**
     * Java的泛型是采用擦拭法实现的；
     * <p>
     * 擦拭法决定了泛型<T>：
     * <p>
     * 不能是基本类型，例如：int；
     * 不能获取带泛型类型的Class，例如：Pair<String>.class；
     * 不能判断带泛型类型的类型，例如：x instanceof Pair<String>；
     * 不能实例化T类型，例如：new T()。
     * 泛型方法要防止重复定义方法，例如：public boolean equals(T obj)；
     * <p>
     * 子类可以获取父类的泛型类型<T>。
     *
     * @param args
     */

    public static void main(String[] args) {
//        Java提供的使用反射API读取Annotation的方法包括：
//        判断某个注解是否存在于Class、Field、Method或Constructor：

//        Class.isAnnotationPresent(Class)
//        Field.isAnnotationPresent(Class)
//        Method.isAnnotationPresent(Class)
//        Constructor.isAnnotationPresent(Class)
// 判断@Report是否存在于Person类:
        boolean annotationPresent = Person.class.isAnnotationPresent(Report.class);
        Class cls = Person.class;
        Report report = (Report) cls.getAnnotation(Report.class);
        if (report != null) {

        }

    }

}

@Target({ElementType.FIELD,})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Check {
    int min() default 0;

    int max() default 0;

    int value() default 0;
}

@Repeatable(Reports.class)
@Target(ElementType.TYPE)
@interface Report {
    int type() default 0;

    String level() default "info";

    String value() default "";
}

@Target(ElementType.TYPE)
@interface Reports {
    Report[] value();
}

class Hello {
    @Check(min = 0, max = 100, value = 55)
    public int n;

    @Check(value = 99)
    public int p;

    @Check(99) // @Check(value=99)
    public int x;

    @Check
    public int y;
}